Navbars Navigation Workflow

quarto
navigation
workflow
deployment
automation
Comprehensive guide to Quarto navigation systems, automated navigation.json generation, and deployment workflows
Author

Dario Airoldi

Published

January 16, 2025

Modified

November 3, 2025

Abstract

A complete guide to implementing and managing navigation workflows in Quarto sites. This document covers navigation architecture, automated navigation.json generation, navbar and sidebar configuration, related pages implementation, development workflows, file management strategies, and troubleshooting guides. Essential for building scalable and maintainable Quarto documentation sites.

Keywords

quarto, navigation, navbar, sidebar, automation, workflow, deployment, github-pages

1 📋 Table of Contents

2 📖 Overview

This document covers the complete navigation workflow for Quarto sites, including automated navigation generation, Related Pages functionality, and integration with GitHub Pages deployment.

4 ⚡ Automated Navigation.json Generation

4.1 How It Works

The navigation.json file powers the Related Pages functionality and is automatically generated from _quarto.yml:

  • When: Only when navigation.json is missing or older than _quarto.yml
  • Where: Generated by scripts/generate-navigation.ps1
  • Trigger: Pre-render hook in _quarto.yml

4.2 Smart Generation Process

# Timestamp-based intelligent regeneration
if ($quartoModified -gt $navModified) {
    Write-Host "navigation.json is older than _quarto.yml - will regenerate"
    $shouldGenerate = $true
} else {
    Write-Host "navigation.json is up to date - skipping generation"
    $shouldGenerate = $false
}

4.3 Technical Implementation

yq Command Used:

yq eval '.website.sidebar.contents' _quarto.yml --output-format=json

PowerShell Processing:

# Extract content and wrap in navigation structure
$extractedContent = & $yqExecutable eval '.website.sidebar.contents' $quartoFile --output-format=json
$navigationStructure = @{
    contents = $extractedContent | ConvertFrom-Json
}
$navigationStructure | ConvertTo-Json -Depth 20 | Out-File -FilePath $navFile

8 🛠️ Development Workflows

8.1 Local Development Options

Option 1: Development Script

./dev-serve.bat

Option 2: Manual Commands

# Generate navigation.json (if needed)
powershell -ExecutionPolicy Bypass -File scripts/generate-navigation.ps1
# Start Quarto preview
quarto preview

Option 3: Standard Quarto (with pre-render hook)

quarto render    # Automatically runs pre-render hook
quarto preview   # Live development server

8.2 GitHub Pages Deployment

Pre-render Integration:

project:
  pre-render: 
    - powershell -ExecutionPolicy Bypass -File scripts/generate-navigation.ps1

Workflow Integration: The GitHub Actions workflow handles:

  1. Environment setup: Quarto installation
  2. Pre-render execution: Navigation generation
  3. Site building: HTML generation
  4. Deployment: GitHub Pages publishing

9 📁 File Management Strategy

9.1 Versioning Strategy

File Purpose Versioned Reason
navigation.json Navigation data ? Yes Ensures consistency across environments
scripts/generate-navigation.ps1 Generator script ? Yes Source code for automation
yq.exe YAML processor ? No Auto-downloaded dependency

9.2 Render Configuration

Comprehensive File Inclusion:

render:
  - "*.qmd"           # Quarto documents
  - "*.md"            # Markdown files
  - "*/README.md"     # Directory documentation
  - "**/README.md"    # Recursive documentation
  - "**/SUMMARY.md"   # Summary files
  - "**/*.md"         # All markdown files

This ensures all referenced files in navigation are properly rendered and available.

10 🔧 Troubleshooting Guide

10.1 Common Issues and Solutions

404 Errors on Navigation Links:

  • ? Check render configuration: Ensure files are included in render list
  • ? Verify file existence: Confirm source files exist
  • ? Case sensitivity: GitHub Pages is case-sensitive
  • ? URL encoding: Special characters need proper encoding

Navigation Generation Failures:

# Manual testing
powershell -ExecutionPolicy Bypass -File scripts/generate-navigation.ps1

# Check yq availability
.\yq.exe --version

# Verify _quarto.yml syntax
yq eval '.' _quarto.yml

GitHub Actions Issues:

  • ? Pre-render hook syntax: Use full PowerShell command
  • ? File permissions: Ensure scripts are executable
  • ? Path handling: Use correct file paths for cross-platform compatibility

10.2 Debugging Client-Side Issues

Console Debugging:

// Enable verbose logging
console.log('?? Current page path:', getCurrentPagePath());
console.log('?? Navigation config loaded:', navigationConfig);
console.log('?? Found siblings:', siblings);

Network Debugging:

  • Check navigation.json loads correctly in browser
  • Verify file is deployed to GitHub Pages
  • Confirm JSON structure is valid

11 ⚡ Performance Optimization

11.1 Build Performance

  • Smart regeneration: Only rebuild navigation.json when needed
  • Timestamp checking: Avoid unnecessary work
  • Cached dependencies: yq.exe downloaded once per environment

11.2 Runtime Performance

  • Lazy loading: Related Pages loads after main content
  • Event delegation: Efficient navigation event handling
  • Responsive design: Mobile optimization reduces complexity

11.3 SEO and Accessibility

Navigation Structure:

  • Semantic HTML: Proper navigation landmarks
  • ARIA labels: Accessibility-friendly navigation
  • SEO-friendly URLs: Clean, descriptive paths
  • Sitemap generation: Automatic via Quarto

12 🚀 Advanced Configuration

12.1 Custom Navigation Patterns

Conditional Navigation:

sidebar:
  contents:
    - text: "---"        # Separator
    - section: "Advanced"
      contents:
        - href: advanced/topic1.md
          text: "Topic 1"
      collapse: true       # Start collapsed

Dynamic Menu Generation: The Related Pages system can be extended for:

  • Tag-based navigation: Show related content by tags
  • Category filtering: Filter by content categories
  • Search integration: Connect with site search
  • Breadcrumb generation: Show navigation path

12.2 Integration with External Systems

API Integration:

// Example: Load dynamic navigation from CMS
async function loadDynamicNavigation() {
    const response = await fetch('/api/navigation');
    const dynamicNav = await response.json();
    renderDynamicNavigation(dynamicNav);
}

This comprehensive navigation workflow ensures a seamless user experience while providing developers with powerful tools for customization and automation.